package com.skinchange.base;

import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.util.ArrayMap;
import android.support.v4.view.LayoutInflaterCompat;
import android.support.v4.view.LayoutInflaterFactory;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.app.AppCompatDelegate;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;

import com.skinchange.attr.SkinAttr;
import com.skinchange.attr.SkinAttrSupport;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

/**
 * Description:
 * Author: Author
 * Date: 2017-08-08
 * Time: 16:34
 */


public class BaseSkinActivity extends AppCompatActivity {
    private static final String TAG = "BaseSkinActivity";

    static final Class<?>[] sConstrutorSignature = new Class[]{
      Context.class,AttributeSet.class};

    private static final String LOG_TAF = "AppCompatViewInflater";

    private static final Map<String, Constructor<? extends View>> sConstrucrorMap = new ArrayMap<>();

    private final Object[] mConstructorArgs = new Object[2];

    private Method mCreateViewMethod = null;

    static final Class<?>[] sCreateViewSignature = new Class[]{View.class,String.class,Context.class,AttributeSet.class};

    private final Object[] mCreateViewArgs = new Object[4];

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {

        LayoutInflater mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        LayoutInflaterCompat.setFactory(mInflater, new LayoutInflaterFactory() {
            @Override
            public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {

                //系统有没有使用setFatory
                //完成appConmpat factory的工作

                AppCompatDelegate delegate = getDelegate();
                View view = null;

                try {

                    if (mCreateViewMethod == null){
                        mCreateViewMethod = delegate.getClass().getMethod("createView",sCreateViewSignature);
                    }
                    mCreateViewArgs[0] = parent;
                    mCreateViewArgs[1] = name;
                    mCreateViewArgs[2] = context;
                    mCreateViewArgs[3] = attrs;

                    view = (View) mCreateViewMethod.invoke(mCreateViewArgs);

                } catch (Exception e) {
                    e.printStackTrace();
                }
                if (view == null){
                    view = createViewFromTag(context,name,attrs);
                }
                if (view != null){

                    List<SkinAttr> skinAttrs = SkinAttrSupport.getSkinAttrs(attrs, context);
                }

                return view;
            }
        });

        super.onCreate(savedInstanceState);
    }

    private View createViewFromTag(Context context,String name,AttributeSet attrs){
        if (name.equals("view")){
            name = attrs.getAttributeValue(null,"class");
        }

        try {
            mConstructorArgs[0] = context;
            mConstructorArgs[1] = attrs;

            if (-1 == name.indexOf('.')){
                return createView(context,name,"android.widget.");
            }else {
                return createView(context,name,null);
            }
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }finally {
            mConstructorArgs[0] = null;
            mConstructorArgs[1] = null;
        }
    }

    private View createView(Context context,String name,String prefix) throws ClassNotFoundException {

        Constructor<? extends View> constructor = sConstrucrorMap.get(name);

        try {
            if (constructor == null) {
                Class<? extends View> clazz = context.getClassLoader().loadClass(
                        prefix != null ? (prefix + name) : name).asSubclass(View.class);
                constructor = clazz.getConstructor(sConstrutorSignature);
                sConstrucrorMap.put(name,constructor);
            }
            constructor.setAccessible(true);
            return constructor.newInstance(mConstructorArgs);
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }
}
